home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw 3D / Documentation / d e v e l o p / Develop Issue 23 article / Geometry Sample / Shell src / FloatingWindowSupport.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-21  |  13.8 KB  |  554 lines  |  [TEXT/MMCC]

  1.  
  2. #include "BuildControl.h"
  3.  
  4.  
  5.  
  6. #if defined(qUseDumpFile)
  7.     #include "DumpHeader.h"
  8. #else
  9.     #include <Resources.h>
  10. #endif
  11.  
  12. #include "FloatingWindowSupport.h"
  13.  
  14.  
  15.  
  16. extern void DoActivate(WindowPtr, Boolean);
  17. extern Boolean GetLastVisibleState(WindowPtr);
  18. extern void SetLastVisibleState(WindowPtr, Boolean);
  19.  
  20.  
  21. //-----------------------------------------------------------------------
  22. // If the hit window is a floater and isn't the frontmost floater, or
  23. // if its a nonfloater and it isn't the frontmost nonfloater, 
  24. // we should select it.
  25. //-----------------------------------------------------------------------
  26. Boolean NeedsSelect(WindowPtr win)
  27. {
  28.     Boolean isntSelected = false;
  29.  
  30.     if ((!IsFloatingWindow(win)) && (win != FrontNonFloatingWindow()))
  31.         isntSelected = true;
  32.     
  33.     else if ((IsFloatingWindow(win)) && (win != FrontWindow()))
  34.         isntSelected = true;
  35.  
  36.     return isntSelected;
  37. }
  38.  
  39. //-----------------------------------------------------------------------
  40.  
  41. Boolean IsFloatingWindow(WindowPtr win)
  42. {
  43.     return ((win != NULL) 
  44.         && (((WindowPeek) win)->windowKind == kApplicationFloaterKind));
  45. }
  46.  
  47. //-----------------------------------------------------------------------
  48.  
  49. Boolean IsModalWindow(WindowPtr win)
  50. {
  51.     short    variant;
  52.     Boolean    isModal = false;
  53.  
  54.     if (win != NULL) {
  55.         variant = GetWVariant((WindowPtr) win);
  56.         if ((((WindowPeek) win)->windowKind == dialogKind) 
  57.             && ((variant == dBoxProc) || (variant == movableDBoxProc)))
  58.             isModal = true;
  59.     }
  60.  
  61.     return isModal;
  62. }
  63.  
  64. //-----------------------------------------------------------------------
  65. // ActivateWindow
  66. //
  67. // Hilites and calls its activate handler.
  68. //-----------------------------------------------------------------------
  69. void ActivateWindow(WindowPtr win)
  70. {
  71.     HighlightActivateWindow(win, true);
  72. }
  73.  
  74. //-----------------------------------------------------------------------
  75. // DeactivateWindow
  76. //
  77. // Unhilites and calls its activate handler.
  78. //-----------------------------------------------------------------------
  79. void DeactivateWindow(WindowPtr win)
  80. {
  81.     HighlightActivateWindow(win, false);
  82. }
  83.  
  84. //-----------------------------------------------------------------------
  85. // HighlightActivateWindow
  86. //
  87. // Common code for ActivateWindow and DeactivateWindow.  Does actual
  88. // highlighting and calling of the activate handler.
  89. //-----------------------------------------------------------------------
  90. void HighlightActivateWindow(WindowPtr win, Boolean activate)
  91. {
  92.     //
  93.     // Calls back to the application shell (gross) to perform the
  94.     // activates needed, since we're dummying them up for our purposes.
  95.     //
  96.     HiliteWindow(win, activate);
  97.     DoActivate(win, activate);
  98. }
  99.  
  100. //-----------------------------------------------------------------------
  101.  
  102. void DragThisWindow(WindowPtr win, Point startPoint, const Rect *bounds)
  103. {
  104.     Rect        dragRect;
  105.     KeyMap        keyMap;
  106.     GrafPtr        savePort;
  107.     GrafPtr        windowMgrPort;
  108.     RgnHandle    dragRegion;
  109.     RgnHandle    windowContentRegion;
  110.     long        dragResult;
  111.     short        topLimit;
  112.     Boolean        commandKeyDown;
  113.     
  114.     if (WaitMouseUp()) {
  115.         //
  116.         // Adjust the top of the dragging rectangle
  117.         //
  118.         topLimit = GetMBarHeight() + 4;
  119.         dragRect = *bounds;
  120.         if (dragRect.top < topLimit)
  121.             dragRect.top = topLimit;
  122.     
  123.         GetPort(&savePort);
  124.         GetWMgrPort(&windowMgrPort);
  125.         SetPort(windowMgrPort);
  126.         SetClip(GetGrayRgn());
  127.         
  128.         //
  129.         // Check to see if the command key is down.  If it is, don’t 
  130.         // bring the window to the front after the move.    
  131.         //
  132.         GetKeys(keyMap);
  133.         commandKeyDown = ((keyMap[1] & 0x8000) != 0);
  134.     
  135.         if ((commandKeyDown == true) || (!IsFloatingWindow(win))) {    
  136.             if (commandKeyDown == false)
  137.                 //
  138.                 // If there are floating windows, clip the dragging 
  139.                 // outline to draw behind the floaters.
  140.                 //
  141.                 ClipAbove(FrontNonFloatingWindow());
  142.             else
  143.                 //            
  144.                 // If the command key was down, clip the outline to 
  145.                 // draw behind any windows above the window being dragged.
  146.                 //
  147.                 ClipAbove(win);
  148.         }
  149.             
  150.         dragRegion = NewRgn();
  151.         CopyRgn(((WindowPeek) win)->strucRgn, dragRegion);
  152.         dragResult = DragGrayRgn(dragRegion, startPoint, &dragRect, 
  153.                         &dragRect, noConstraint, NULL);
  154.     
  155.         SetPort(savePort);
  156.  
  157.         if (dragResult != 0) {
  158.             short        newHoriz, newVert;
  159.             short        horizOffset, vertOffset;
  160.  
  161.             horizOffset = dragResult & 0xFFFF;
  162.             vertOffset = dragResult >> 16;
  163.             //
  164.             // Only move it if it stayed inside the dragging box.
  165.             //
  166.             if (vertOffset != -32768) {
  167.                 windowContentRegion = ((WindowPeek) win)->contRgn;
  168.                 newHoriz = (*windowContentRegion)->rgnBBox.left + horizOffset;
  169.                 newVert = (*windowContentRegion)->rgnBBox.top + vertOffset;
  170.                 MoveWindow(win, newHoriz, newVert, false);                
  171.             }
  172.         }
  173.     
  174.         //
  175.         // Bring the window forward if the command key wasn’t down
  176.         //
  177.         if (commandKeyDown == false)
  178.             SelectThisWindow(win);
  179.     
  180.         DisposeRgn(dragRegion);
  181.     }
  182. }
  183.  
  184. //-----------------------------------------------------------------------
  185.  
  186. void SelectThisWindow(WindowPtr win)
  187. {
  188.     WindowPtr            currentFront;
  189.     WindowPtr            lastFloat;
  190.     Boolean                itFloats;
  191.  
  192.     itFloats = IsFloatingWindow(win);
  193.  
  194.     if (itFloats)
  195.         currentFront = FrontWindow();
  196.  
  197.     else {
  198.         currentFront = FrontNonFloatingWindow();
  199.         lastFloat = LastFloatingWindow();
  200.     }
  201.  
  202.     if (currentFront != win) {
  203.         //
  204.         // Selecting floating windows is easy since they’re always active
  205.         //
  206.         if (itFloats)
  207.             BringToFront(win);
  208.     
  209.         else {
  210.             //
  211.             // If there are no floating windows, call SelectWindow
  212.             //
  213.             if (lastFloat == NULL)
  214.                 SelectWindow(win);
  215.         
  216.             else {
  217.                 //
  218.                 // Else we a nonfloating window has been selected and
  219.                 // there are floaters.  Deactivate the window
  220.                 // currently in front, send the selected window behind
  221.                 // the last floater and activate it.
  222.                 //    
  223.                 DeactivateWindow(currentFront);
  224.                 SendBehind(win, lastFloat);
  225.                 ActivateWindow(win);
  226.             }
  227.         }
  228.     }
  229. }
  230.  
  231. //-----------------------------------------------------------------------
  232. //    Return the first visible window that is not a floating window.
  233. //-----------------------------------------------------------------------
  234. WindowPtr FrontNonFloatingWindow()
  235. {
  236.     WindowPtr    win = FrontWindow();
  237.     
  238.     while (win != NULL) {
  239.         if ((!IsFloatingWindow(win)) && (!IsModalWindow(win))
  240.             && ((WindowPeek) win)->visible == true)
  241.             break;
  242.         
  243.         win = (WindowPtr) ((WindowPeek) win)->nextWindow;
  244.     }
  245.  
  246.     return win;
  247. }
  248.  
  249. //-----------------------------------------------------------------------
  250. // Return the last floating window, whether it is visible or not, or 
  251. // NULL if there are no floating windows.
  252. //-----------------------------------------------------------------------
  253. WindowPtr LastFloatingWindow(void)
  254. {
  255.     WindowPtr    win;
  256.     WindowPtr    lastFloat;
  257.     
  258.     win = (WindowPtr) LMGetWindowList();
  259.     lastFloat = NULL;
  260.     
  261.     while (win != NULL) {
  262.         if (IsFloatingWindow(win))
  263.             lastFloat = win;
  264.         win = (WindowPtr) ((WindowPeek) win)->nextWindow;
  265.     }
  266.     
  267.     return lastFloat;
  268. }
  269.  
  270.  
  271. //-----------------------------------------------------------------------
  272.  
  273. void PutNonFloatingWindowInList(WindowPtr win, WindowPtr behind)
  274. {
  275.     require(IsFloatingWindow(win) == false, PuttingFloaterInWrongList);
  276.  
  277.     if (behind == (WindowPtr) -1) {
  278.         //
  279.         // If -1, put this window at the front of the non floater list.
  280.         //
  281.         behind = LastFloatingWindow();
  282.         
  283.         if (behind == NULL)
  284.             BringToFront(win);
  285.     }
  286.     else
  287.         SendBehind(win, behind);
  288.  
  289. PuttingFloaterInWrongList:
  290.     NormalizeWindowList();
  291.     return;
  292. }
  293.  
  294. //-----------------------------------------------------------------------
  295.  
  296. void ShowThisWindow(WindowPtr win)
  297. {
  298.     WindowPtr            behind;
  299.     WindowPtr            frontNonFloater;
  300.     Boolean                activateIt = false;
  301.     
  302.     NormalizeWindowList();
  303.     if ((((WindowPeek) win)->visible != false))
  304.         return;
  305.         
  306.     frontNonFloater = FrontNonFloatingWindow();
  307.     
  308.     if (!IsFloatingWindow(win)) {
  309.         //
  310.         // We're showing a non-floater.  Grab the next window and if
  311.         // its the frontmost non floater, unhilite it and prepare win
  312.         // to be hilited.
  313.         //
  314.         behind = (WindowPtr) ((WindowPeek) win)->nextWindow;
  315.  
  316.         if ((behind == frontNonFloater) || (frontNonFloater == NULL)) {
  317.             if (behind != NULL)
  318.                 DeactivateWindow(behind);
  319.  
  320.             ((WindowPeek) win)->hilited = true;
  321.             activateIt = true;
  322.         }
  323.     }
  324.     else {        
  325.         //
  326.         // We're showing a floater.  Check to see if a modal window is 
  327.         // up before trying to highlight this one.  If so, show this
  328.         // but don't hilite it.
  329.         //
  330.         if ((frontNonFloater != NULL) && (frontNonFloater == FrontWindow()) 
  331.             && (IsModalWindow(frontNonFloater)))
  332.             ((WindowPeek) win)->hilited = false;
  333.  
  334.         else {
  335.             ((WindowPeek) win)->hilited = true;
  336.             activateIt = true;
  337.         }
  338.     }
  339.     
  340.     //
  341.     // Show the window and activate/hilite it if necessary
  342.     //
  343.     ShowHide(win, true);
  344.     
  345.     if (activateIt)
  346.         DoActivate(win, true);
  347. }
  348.  
  349. //-----------------------------------------------------------------------
  350. // HideThisWindow
  351. //
  352. // Hide the specified window.  If it is frontmost, move it behind 
  353. // the window immediately behind it, like HideWindow does.
  354. //-----------------------------------------------------------------------
  355. void HideThisWindow(WindowPtr windowToHide)
  356. {
  357.     WindowPtr    behind, newFront;
  358.     Boolean        itFloats;
  359.  
  360.     if (((WindowPeek) windowToHide)->visible == false)
  361.         return;
  362.     
  363.     itFloats = IsFloatingWindow(windowToHide);
  364.  
  365.     DeactivateWindow(windowToHide);
  366.     ShowHide(windowToHide, false);
  367.  
  368.     behind = (WindowPtr) ((WindowPeek) windowToHide)->nextWindow;
  369.  
  370.     //
  371.     // If there is a window to move this one behind and it's not a floater,
  372.     // or if it is a floater, and we're moving it behind another floater,
  373.     // go ahead and reorder the list.
  374.     //
  375.     if ((behind != NULL) && (behind != windowToHide) 
  376.         && ((itFloats == false) 
  377.             || ((itFloats == true) && (IsFloatingWindow(behind)))))
  378.         SendBehind(windowToHide, behind);
  379.  
  380.     if (itFloats == false)
  381.         newFront = FrontNonFloatingWindow();
  382.     else
  383.         //
  384.         // If the last window we hid was a floater, we shouldn't have to
  385.         // activate anything because all should be fine.  
  386.         //
  387.         newFront = NULL;
  388.  
  389.     if (newFront != NULL)
  390.         ActivateWindow(newFront);
  391. }
  392.  
  393.  
  394.  
  395. //-----------------------------------------------------------------------
  396. // SuspendFloaters
  397. //
  398. // Hide any visible floating windows and deactivate the frontmost 
  399. // document window.
  400. //-----------------------------------------------------------------------
  401. void SuspendFloaters(void)
  402. {
  403.     WindowPtr    win;
  404.     Boolean        windowIsVisible;
  405.     
  406.     win = (WindowPtr) LMGetWindowList();
  407.     if (!IsFloatingWindow(win))
  408.         return;
  409.         
  410.     do {
  411.         windowIsVisible = ((WindowPeek) win)->visible;
  412.         SetLastVisibleState(win, windowIsVisible);
  413.         if (windowIsVisible)
  414.             ShowHide(win, false);
  415.         win = (WindowPtr) ((WindowPeek) win)->nextWindow;
  416.     } while ((win != NULL) && (IsFloatingWindow(win)));
  417.     
  418.     //
  419.     // The floating windows are now hidden.  Deactivate the 
  420.     // first visible document window.
  421.     //
  422.     win = FrontNonFloatingWindow();
  423.     if (win != NULL)
  424.         DeactivateWindow(win);
  425. }
  426.  
  427. //-----------------------------------------------------------------------
  428. // ResumeFloaters
  429. //
  430. // Reveal and activate floating windows that were hidden at suspend. 
  431. // The frontmost document is also activated.
  432. //-----------------------------------------------------------------------
  433. void ResumeFloaters(void)
  434. {
  435.     WindowPtr    win;
  436.     Boolean        windowWasVisible;
  437.     
  438.     NormalizeWindowList();
  439.     win = (WindowPtr) LMGetWindowList();
  440.     if (!IsFloatingWindow(win))
  441.         return;
  442.         
  443.     do {
  444.         windowWasVisible = GetLastVisibleState(win);
  445.         if (windowWasVisible) {
  446.             ShowHide(win, true);
  447.             ActivateWindow(win);
  448.         }
  449.         win = (WindowPtr) ((WindowPeek) win)->nextWindow;
  450.     } while ((win != NULL) && (IsFloatingWindow(win)));
  451.  
  452.     //
  453.     // The floating windows have been revealed.  Activate the 
  454.     // first document window as well.
  455.     //
  456.     win = FrontNonFloatingWindow();
  457.     if (win != NULL)
  458.         ActivateWindow(win);
  459. }
  460.  
  461. //-----------------------------------------------------------------------
  462.  
  463. void NormalizeWindowList()
  464. {
  465.     WindowPtr    current = (WindowPtr) LMGetWindowList();
  466.     WindowPtr    next, behind = NULL;
  467.  
  468.     //
  469.     // Put modal windows in front
  470.     //    
  471.     while (current != NULL) {
  472.         next = (WindowPtr) ((WindowPeek) current)->nextWindow;
  473.  
  474.         if ((current != NULL) && (IsModalWindow(current))) {
  475.             if (behind == NULL) {
  476.                 if (current != (WindowPtr) LMGetWindowList())
  477.                     BringToFront(current);
  478.             } 
  479.             else if (current != (WindowPtr) ((WindowPeek) behind)->nextWindow)
  480.                 SendBehind(current, behind);
  481.  
  482.             behind = current;
  483.         }
  484.         current = next;
  485.     }
  486.     
  487.     //
  488.     // Put floating windows behind last modal
  489.     //
  490.     current = (WindowPtr) LMGetWindowList();
  491.     
  492.     while (current != NULL) {
  493.         next = (WindowPtr) ((WindowPeek) current)->nextWindow;
  494.  
  495.         if ((current != NULL) && (IsFloatingWindow(current))) {
  496.             if (behind == NULL) {
  497.                 if (current != (WindowPtr) LMGetWindowList())
  498.                     BringToFront(current);
  499.             }
  500.             else if (current != (WindowPtr) ((WindowPeek) behind)->nextWindow)
  501.                 SendBehind(current, behind);
  502.  
  503.             behind = current;
  504.         }
  505.         current = next;
  506.     }
  507. }
  508.  
  509. //-----------------------------------------------------------------------
  510. // Call this before EVER showing a modal window.
  511. //-----------------------------------------------------------------------
  512. void PrepareForModalWindow()
  513. {
  514.     WindowPtr    win;
  515.  
  516.     win = FrontWindow();
  517.     while (win != NULL) {
  518.         if (((WindowPeek) win)->visible == true)
  519.             DeactivateWindow(win);
  520.         win = (WindowPtr) ((WindowPeek) win)->nextWindow;
  521.     }
  522. }
  523.  
  524. //-----------------------------------------------------------------------
  525. // Call this after dismissing a modal window.
  526. //
  527. // PowerPlant does this very nicely..
  528. //
  529. //    Starting with the front window, activate all visible windows up
  530. //    to and including the first visible non-floating window.
  531. //    Why this works:
  532. //        > If the front window is modal, it gets activated and
  533. //            the loop stops because it's not floating.
  534. //        > If the front window is floating, windows keep getting
  535. //            activated until the first regular window is activated.
  536. //        > If the front window is regular, it gets activated and
  537. //            the loop stops because it's not floating.
  538. //-----------------------------------------------------------------------
  539. void RecoverFromModalWindow()
  540. {
  541.     WindowPtr    win;
  542.  
  543.     NormalizeWindowList();    
  544.     win = FrontWindow();
  545.     while (win != NULL) {
  546.         if (((WindowPeek) win)->visible == true) {
  547.             ActivateWindow(win);
  548.  
  549.             if (IsFloatingWindow(win) == false)
  550.                 break;
  551.         }
  552.         win = (WindowPtr) ((WindowPeek) win)->nextWindow;
  553.     }
  554. }